package com.rcache.core.persistence;

import com.distributed.netty.entity.JobType;
import com.rcache.core.Element;
import com.rcache.core.cache.Rcache;
import com.rcache.core.exception.DataPersistenceException;
import com.rcache.core.persistence.jobentity.JobElementCache;
import com.rcache.core.persistence.strategy.BasePersistenceStrategy;
import com.rcache.core.persistence.utils.FileUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Desc
 * @Author MrPeng
 * @TIME 2022/6/9 22:46
 **/
public class DateSizePersistenceImpl extends BasePersistenceStrategy {

    static Map<Rcache,DateSizePersistenceImpl> persistences=new HashMap<>();
    private List<JobElementCache> jobElementCacheList=new ArrayList<>();
    public static DateSizePersistenceImpl getInstance(Rcache rcache){
        DateSizePersistenceImpl persistence = persistences.get(rcache);
        if (persistence==null){
            persistence=new DateSizePersistenceImpl();
            persistences.put(rcache,persistence);
        }
        return persistence;
    }

    @Override
    public boolean put(Rcache cache, Element element) throws DataPersistenceException {
        JobElementCache jobElementCache = new JobElementCache(cache, element, JobType.PUT);
        jobElementCacheList.add(jobElementCache);
        try {
            return executeJob(jobElementCacheList,cache);
        } catch (IOException e) {
            throw new DataPersistenceException(e);
        } catch (ClassNotFoundException e) {
            throw new DataPersistenceException(e);
        }
    }



    @Override
    public boolean replace(Rcache cache, Element element) throws DataPersistenceException {
        JobElementCache jobElementCache = new JobElementCache(cache, element, JobType.UPDATE);
        jobElementCacheList.add(jobElementCache);
        try {
            return executeJob(jobElementCacheList,cache);
        } catch (IOException e) {
            throw new DataPersistenceException(e);
        } catch (ClassNotFoundException e) {
            throw new DataPersistenceException(e);
        }
    }

    @Override
    public boolean remove(Rcache cache, Element element) throws DataPersistenceException {
        JobElementCache jobElementCache = new JobElementCache(cache, element, JobType.DELETE);
        jobElementCacheList.add(jobElementCache);
        try {
            return executeJob(jobElementCacheList,cache);
        } catch (IOException e) {
            throw new DataPersistenceException(e);
        } catch (ClassNotFoundException e) {
            throw new DataPersistenceException(e);
        }
    }

    @Override
    public Element get(Rcache cache, Object ElementKey) throws DataPersistenceException {
        String newPath = cache.getDiskCachePath() + "/" + cache.getCacheName();
        try {
            return FileUtils.getFile(newPath,ElementKey);
        } catch (IOException e) {
            throw new DataPersistenceException(e);
        } catch (ClassNotFoundException e) {
            throw new DataPersistenceException(e);
        }
    }

    @Override
    public Integer getSize(Rcache cache) throws DataPersistenceException {
        String newPaht = cache.getDiskCachePath() + "/" + cache.getCacheName();
        return FileUtils.numberOfFiles(newPaht);
    }

    @Override
    public boolean tryRestoreFromLocal(Rcache cache) throws DataPersistenceException {
        return false;
    }

    /**
     * @param jobElementCacheList
     * @param cache
     * @return
     * @desc 执行任务
     */
    private boolean executeJob(List<JobElementCache> jobElementCacheList, Rcache cache) throws IOException, ClassNotFoundException {
        if (jobElementCacheList.size()>cache.getDiskCacheSize()) {
            String newPath = cache.getDiskCachePath() + "/" + cache.getCacheName();
            for (JobElementCache jobElement : jobElementCacheList) {
                JobType type = jobElement.getJobType();
                switch (type) {
                    case PUT:
                        FileUtils.putFlie(newPath, jobElement.getElement());
                        break;

                    case UPDATE:
                        FileUtils.putFlie(newPath, jobElement.getElement());
                        break;

                    case DELETE:
                        FileUtils.deleteFile(newPath);
                        break;
                }
            }
            jobElementCacheList.clear();
            return true;
        }
        return false;
    }
}
